game_zone = (48, 165)

grid_w = 40
grid_h = 40
def get_grid_centre(col,row,zone_topleft =game_zone):
    x,y = zone_topleft
    return x+ col * grid_w + 0.5 * grid_w ,y+row*grid_h+ 0.5*grid_h

def get_grid_topleft(col,row,zone_topleft =game_zone):
    x,y = zone_topleft
    return    x+col * grid_w , y+row*grid_h 

def get_square_grid_topleft(col,row,zone_topleft =game_zone):
    x,y = zone_topleft
    return    x+col * grid_w-2 , y+row*grid_h -13

def get_grid_idx(x,y,zone_topleft =game_zone):
    sx,sy = zone_topleft
    x-=sx
    y-=sy
    return  int(x/grid_w),int(y/grid_h)
def get_grid_centre_from_x_y(x,y,zone_topleft =game_zone):
    c,r = get_grid_idx(x,y,zone_topleft)
    x,y = get_grid_centre(c,r,zone_topleft)
    return x,y
def new_obj(position_object,p):
    r = random(0,3)
    ks = list(position_object.keys())
    objname = ks[int(r)]
    #p = get_grid_idx(random(0,w),random(0,h))
    position_object[objname].append(p)



def get_inverted_obj_map(position_object):
    d = {}
    for k ,ps in position_object.items():
        for p in ps:
            d[p] = k
    return d

def is_player_on_obj_pv(pV,obj_map):
    player_p= get_grid_idx(pV.x,pV.y)
    return  obj_map.get(player_p),player_p
        
def get_inverted_obj_map(position_object):
    d = {}
    for k ,ps in position_object.items():
        for p in ps:
            d[p] = k
    return d

def is_player_on_obj(pos,obj_map):
    x,y = pos
    player_p= get_grid_idx(x,y)
    return  obj_map.get(player_p),player_p

def get_target(botx_grid,boty_grid,w=15,h=13):
    targets = []
    for i in range(-3,3):
        for j in range(-3,3):
            if i == 0 or j== 0:
                continue
            if 0<=botx_grid+ i<w and 0<=boty_grid+ j<h:
                targets.append((i,j))
    return targets
def get_random_target(botx_grid,boty_grid):
    targets = get_target(botx_grid,boty_grid)
    l = len(targets)
    targetx, targety= targets[int(random(0,l))]        
    target  =botx_grid+ targetx,boty_grid+ targety
    
    return target
def get_bot_power(bot):
    return bot['player_state']['obj']['power']
def bot_add_obj(bot, obj):
    bot['player_state']['obj'][obj]+=1
    

def new_player_state():
    return {'obj':
         {'number': 0, 'speed': 0, 'power': 0}, 
         'speed': 10,'s':0,'current_direction':'down','isBot':True,'trap':False}
    
def find_attrack_place(boom_p,r):
    res = find_places(boom_p,r)
    att = []
    for p in res:
        if  is_at_boom_range(p,boom_p):
            att.append(p)
    return att

def in_bot_attract_range(boom_p,r,target):
    a = find_attrack_place(boom_p,r)
    if isinstance(a,list):
        if target in a:
            return True
    return False
def is_neighbood(p1,p2):
    x,y = p1
    x2,y2 = p2
    if x== x2 and abs(y-y2) ==1:
        return True
    if y==y2 and abs(x-x2)==1:
        return True
    return False


def is_at_boom_range(p1,p2):
    x,y = p1
    x2,y2 = p2
    return x==x2 or y == y2
def find_places(boom_p,r):
    x,y = boom_p
    xs  = [x]
    for i in range(r+1):
        xs.append(x+i)
        xs.append(x-i)
        
    ys  = [y]
    for i in range(r+1):
        ys.append(y+i)
        ys.append(y-i)
    ys = list(set(ys))
    xs = list(set(xs))
    res = []
    for x in xs:
        for y in ys:
            res.append((x,y))
    return res

def find_boom_place(center,r,bubble_time):
    res = find_places(center,r)
    booms = []
    for p in res:
        if p in bubble_time:
            booms.append(p)
    return booms
def find_obj_place(center, r, position_object):
    res = find_places(center, r)
    booms = []
    for p in res:
        for pos_es in position_object.values():
            if p in pos_es:
                booms.append(p)
    return booms        


def in_bot_attract_range(boom_p,r,target):
    a = find_attrack_place(boom_p,r)
    if isinstance(a,list):
        if target in a:
            return True
    return False
def find_safe_place(boom_p,r):
    res = find_places(boom_p,r)
    safes = []
    #print({'search_rage':res})
    for p in res:
        if not is_at_boom_range(p,boom_p):
            safes.append(p)
    #print({'search_safes':safes})
    return safes

def find_nearest_safe(bot_p , boom_p,r):
    safes = find_safe_place(boom_p,r)
    botx,boty = bot_p
    safes = sorted(safes,key = lambda x:abs(x[0] - botx)+ abs(x[1] - boty))
    return safes

def find_nearest_attrack(target_bot_p , boom_p,r):
    safes = find_attrack_place(boom_p,r)
    botx,boty = target_bot_p
    safes = sorted(safes,key = lambda x:abs(x[0] - botx)+ abs(x[1] - boty))
    return safes



def find_nearest_obj(center , r,position_object):
    safes = find_obj_place(center,r,position_object)
    botx,boty = center
    safes = sorted(safes,key = lambda x:abs(x[0] - botx)+ abs(x[1] - boty))
    return safes
    
def get_path(node_father,end_node):
    
    cur = end_node
    paths = [cur]
    while cur in node_father:
        cur = node_father[cur]
        paths.insert(0,cur)
    return paths

def Astar_finder(startp,endp,forbids,width_range, height_range):
    node_father = {}
   
    has_visited = []
    search_pos = [startp]
    cur = ''
    if startp in forbids or endp in forbids:
        return []
    assert startp not in forbids
    assert endp not in forbids
    while search_pos!=[] and cur != endp:
        search_pos = sorted(search_pos,key=lambda x : abs(x[0]-endp[0])+abs(x[1]-endp[1]) ,reverse=True)
        cur = search_pos.pop()
        has_visited.append(cur)
        dmap = {'left':(-1,0),'right':(1,0),'up':(0,-1),'down':(0,1)}
        for direction, displacement in dmap.items():
            dx,dy =displacement
            cx,cy = cur
           
            if 0<= cx+dx <width_range and 0<= cy+dy<height_range:
                if (cx+dx,cy+dy) in forbids:
                    continue
                if (cx+dx,cy+dy) not in has_visited:
                    search_pos.append((cx+dx,cy+dy))
                    node_father[(cx+dx,cy+dy)] = cur
        
        if len(search_pos)>15*13:
            break
    
    if  len(has_visited) != len(set(has_visited)):
        print('!!no eq')
    return get_path(node_father,endp)
    #return has_visited,node_father
def is_bot_alive(bot):
    return bot['state'] == 'alive'

def is_bot_trap(bot):
    return bot['player_state']['trap']
